package model.entity.stats;

import java.util.ArrayList;
import java.util.List;
import utilities.*;

public abstract class DerivedStat implements Archiveable {
	// Instance Variables
	protected List<StatModifier> modifiers;
	protected List<Stat> derivationValues; 
	
	// Constructor
	
	/**
	 * Constructor: creates an empty modifiers list
	 */
	public DerivedStat() {
		this.modifiers = new ArrayList<StatModifier>();
		this.derivationValues = new ArrayList<Stat>();
	}
	
	
	/**
	 * @param modifiers
	 * @param derivationValues
	 */
	public DerivedStat(List<StatModifier> modifiers, List<Stat> derivationValues)
	{
		this.modifiers = modifiers;
		this.derivationValues = derivationValues;
	}



	// Getters
	/**
	 * This abstract method returns the derived (calculated) value of this stat
	 */
	abstract public double getValue();
	
	
	// Stat Modifiers
	/**
	 * Returns the stat modifier for the specified key, null otherwise
	 */
	public StatModifier getStatModifier(String key) {
		for (StatModifier m : this.modifiers) {
			if (m.getName() == key) {
				return m;
			}
		}
		return null;
	}
	
	/**
	 * Adds the modifier to the list
	 * @param modifier
	 */
	public void addStatModifier(StatModifier modifier) {
		this.modifiers.add(modifier);
	}
	
	/**
	 * Removes the specified modifier from the list, and returns it
	 * @param key
	 * @return the removed modifier, or null if there is not a modifier for
	 * the specified name
	 */
	public StatModifier removeStatModifier(String key) {
		StatModifier modifier = null;
		for (StatModifier m : this.modifiers) {
			if (m.getName() == key) {
				modifier = m;
				break;
			}
		}
		return modifier;
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		return super.toString() + ": " + this.getValue();
	}
	
	
	public Archive save() {
		Archive archive = ArchiveFactory.createArchive();
		
		List<String> derivationValuesClassList = new ArrayList<String>(this.derivationValues.size());
		for (Stat stat : this.derivationValues) {
			derivationValuesClassList.add(stat.getClass().getName());
		}
		archive.putAttributeList("derivationValuesClassList", derivationValuesClassList);
		archive.putManyRelationship("derivationValues", this.derivationValues);
		
		List<String> modifiersClassList = new ArrayList<String>(this.modifiers.size());
		for (StatModifier modifier : this.modifiers) {
			modifiersClassList.add(modifier.getClass().getName());
		}
		archive.putAttributeList("modifiersClassList", modifiersClassList);
		archive.putManyRelationship("modifiers", this.modifiers);
		
		return archive;
	}
	
	public void load(Archive archive) {
		List<String> derivationValuesClassList = archive.getAttributeList("derivationValuesClassList");
		List<Archive> derivationValuesArchives = archive.getManyRelationship("derivationValues");
		this.derivationValues = new ArrayList<Stat>();
		for (int i = 0; i < derivationValuesClassList.size(); i++) {
			Stat stat = (Stat)ModelFactory.getInstance().createInstanceWithClassName(derivationValuesClassList.get(i));
			stat.load(derivationValuesArchives.get(i));
			
			this.derivationValues.add(stat);
		}
		
		List<String> modifiersClassList = archive.getAttributeList("modifiersClassList");
		List<Archive> modifiersArchives = archive.getManyRelationship("modifiers");
		this.modifiers = new ArrayList<StatModifier>();
		for (int i = 0; i < modifiersClassList.size(); i++) {
			StatModifier modifier = (StatModifier)ModelFactory.getInstance().createInstanceWithClassName(modifiersClassList.get(i));
			modifier.load(modifiersArchives.get(i));
			
			this.modifiers.add(modifier);
		}
	}
}
